<template>
  <div class="login" id="iviewUi">
    <h2 class="login-title">移动终端管理平台</h2>
    
    <!-- <div class="toppng">
    </div> -->

    <div class="login-area">
      <div class="qrimmg-area" @click="qrlogin"></div>

      <h2 class="login-area-title">移动终端管理平台登录</h2>
      <div class="login-from">
        <el-form ref="form" :model="form" :rules="rules">
          <el-form-item prop="username">
            <el-input v-model="form.username" placeholder="手机/用户名/邮箱">
              <i slot="prefix" class="el-input__icon el-icon-user"></i>
            </el-input>
          </el-form-item>
          <el-form-item prop="password">
            <el-input
              type="password"
              v-model="form.password"
              placeholder="输入密码"
            >
              <i slot="prefix" class="el-input__icon el-icon-lock"></i>
            </el-input>
          </el-form-item>
          <!-- <el-form-item prop="verifycode" v-show="false">
            <el-row :gutter="20">
              <el-col :span="12">
                <el-input
                  v-model="form.code"
                  placeholder="输入验证码"
                  @keyup.enter.native="onLogin"
                >
                  <i slot="prefix" class="el-input__icon el-icon-lock"></i>
                </el-input>
              </el-col>
              <el-col :span="12">
                <div class="verification-img">
                  <img
                    :src="verifyCodeImgUrl"
                    @click="reloadVerifyCode"
                    alt="加载验证码"
                    style="width: 170px; cursor: pointer; display: block"
                  />
                </div>
              </el-col>
            </el-row>
          </el-form-item> -->
          <el-checkbox
            v-model="form.rememberMe"
            style="margin: 0px 0px 25px 0px"
            >记住密码</el-checkbox
          >
          <el-form-item>
            <el-button
              :loading="loading"
              type="primary"
              native-type="submit"
              @click.native.prevent="onLogin"
            >
              <span v-if="!loading">登录</span>
              <span v-else>登录中...</span>
            </el-button>
          </el-form-item>
        </el-form>
      </div>
    </div>

    <!--验证码弹窗-->
    <div class="verPopover" v-show="visible">
      <VerificationImg
        ref="verificationImg"
        @closePupUp="closePupUp"
        @login="login"
      />
    </div>

    <!--二维码弹窗-->
    <div class="qrbody" v-show="qrVisible">
      <vue-qr
        style="margin-top: 20px; border: 1px solid #ccc"
        :text="qrtxt"
        :size="300"
        :logoScale="0.3"
        :margin="15"
        colorDark="#545c64" colorLight="#fff"
        
      ></vue-qr>
      <p class="top-text">APP 扫一扫登陆</p>
    </div>

    
  </div>
</template>

<script>
import mqtt from "mqtt";
import vueQr from "vue-qr/src/packages/vue-qr.vue";
import { Encrypt, Decrypt } from "@/utils/encoder";
import { setToken, removeToken } from "@/utils/auth";
import { listMenu } from "@/http/api/menu";
import constants from "@/http/constants";
import VerificationImg from "../../components/VerificationImg.vue";
//引入three.js 粒子
import * as THREE from "three";

export default {
  components: {
    VerificationImg,
    vueQr,
  },

  //粒子
  props: {
    amountX: {
      type: Number,
      default: 50,
    },
    amountY: {
      type: Number,
      default: 50,
    },
    //控制点颜色
    color: {
      type: String,
      default: "#097bdb",
    },
    top: {
      type: Number,
      default: 350,
    },
  },
  //粒子

  data: function () {
    return {

      bgimg:"@/assets/top.png",
      qrVisible: false, //二维码弹窗开启关闭
      visible: false, //弹窗开启关闭

      qrtxt: "", //二维码内容

      verifyCodeImgUrl: "",
      form: {
        username: "admin",
        password: "admin", //admin123  123自己手输入
        rememberMe: false,
        code: "",
        uuid: "",
      },
      rules: {
        username: [
          { required: true, message: "请输入用户名", trigger: "blur" },
        ],
        password: [{ required: true, message: "请输入密码", trigger: "blur" }],
      },
      loading: false,

      //粒子
      count: 0,
      // 用来跟踪鼠标水平位置
      mouseX: 0,
      windowHalfX: null,
      // 相机
      camera: null,
      // 场景
      scene: null,
      // 批量管理粒子
      particles: null,
      // 渲染器
      renderer: null,
      //粒子


       //MQ  控制路由页面
       navs: [
        // { command: "首页", path: "/system/work" },
        // { command: "用户管理", path: "/system/user" },
        // { command: "分配角色", path: "/system/auth-role/:userId" },
        // { command: "角色管理", path: "/system/role" },
        // { command: "分配用户", path: "/system/auth-user/:roleId" },
        // { command: "菜单管理", path: "/system/menu" }
      ]


    };
  },

  methods: {
    // 二维码登录按钮
    qrlogin() {

      this.qrtxt=this.uuid2(16, 16);

      this.qrVisible = !this.qrVisible;
      if(this.qrVisible)
      this.sysConnection();
      else
      this.destroyConnection();
    },

    //// 登录按钮
    onLogin() {
      this.$refs.verificationImg.refreshCaptcha();

      this.$refs.form.validate((valid) => {
        if (valid) {
          this.visible = true;
        }
      });
    },

    // 关闭验证码弹框
    closePupUp() {
      this.visible = false;
    },
    // 登录
    login(uuid, movePercent) {
      this.loading = true;

      var encoderStr = Encrypt(this.form.password);
      // console.log('密:'+encoderStr)
      // console.log('解密:'+Decrypt(encoderStr))

      let data = {
        username: this.form.username,
        password: encoderStr,
        rememberMe: this.form.rememberMe,
        code: movePercent,
        uuid: uuid,
      };

      this.$refs.form.validate(async (valid) => {
        if (valid) {
          this.$post(
            "/auth/login",
            data,
            (data) => {
              this.loading = false;
              this.$message({ message: "登录成功", type: "success" });
              // this.$store.dispatch("updateToken", data.data.access_token); 
              setToken(data.token);  //boot版
              // setToken(data.data.access_token); //cloud版
              this.form.password = "";
              this.$router.push({ name: "Home" });
            },
            (error) => {
              this.$message.error(error.msg);
              this.loading = false;
              this.$refs.verificationImg.refreshCaptcha();
            }
          );

          // let res = await this.$api.post('/auth/login',this.form)
          // this.$message({message: res.msg,type: 'success'})
          // this.$store.dispatch('updateUser',res.data)
          // this.$router.push({name: 'Home'})
        } else {
          return false;
        }
      });
    },

    ////////////////////////////////////////////////粒子
    init: function () {
      const SEPARATION = 100;
      const SCREEN_WIDTH = window.innerWidth;
      const SCREEN_HEIGHT = window.innerHeight;
      const container = document.createElement("div");
      this.windowHalfX = window.innerWidth / 2;
      container.style.position = "relative";
      container.style.top = `${this.top}px`;
      container.style.height = `${SCREEN_HEIGHT - this.top}px`;
      document.getElementById("iviewUi").appendChild(container);

      this.camera = new THREE.PerspectiveCamera(
        75,
        SCREEN_WIDTH / SCREEN_HEIGHT,
        1,
        10000
      );
      this.camera.position.z = 1000;

      this.scene = new THREE.Scene();

      const numParticles = this.amountX * this.amountY;
      const positions = new Float32Array(numParticles * 3);
      const scales = new Float32Array(numParticles);
      // 初始化粒子位置和大小
      let i = 0;
      let j = 0;
      for (let ix = 0; ix < this.amountX; ix++) {
        for (let iy = 0; iy < this.amountY; iy++) {
          positions[i] = ix * SEPARATION - (this.amountX * SEPARATION) / 2;
          positions[i + 1] = 0;
          positions[i + 2] = iy * SEPARATION - (this.amountY * SEPARATION) / 2;
          scales[j] = 1;
          i += 3;
          j++;
        }
      }

      const geometry = new THREE.BufferGeometry();
      geometry.addAttribute(
        "position",
        new THREE.BufferAttribute(positions, 3)
      );
      geometry.addAttribute("scale", new THREE.BufferAttribute(scales, 1));
      // 初始化粒子材质
      const material = new THREE.ShaderMaterial({
        uniforms: {
          color: { value: new THREE.Color(this.color) },
        },
        vertexShader: `
          attribute float scale;
          void main() {
            vec4 mvPosition = modelViewMatrix * vec4( position, 2.0 );
            gl_PointSize = scale * ( 300.0 / - mvPosition.z );
            gl_Position = projectionMatrix * mvPosition;
          }
        `,
        fragmentShader: `
          uniform vec3 color;
          void main() {
            if ( length( gl_PointCoord - vec2( 0.5, 0.5 ) ) > 0.475 ) discard;
            gl_FragColor = vec4( color, 1.0 );
          }
        `,
      });

      this.particles = new THREE.Points(geometry, material);
      this.scene.add(this.particles);

      this.renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
      this.renderer.setSize(container.clientWidth, container.clientHeight);
      this.renderer.setPixelRatio(window.devicePixelRatio);
      this.renderer.setClearAlpha(0);
      container.appendChild(this.renderer.domElement);

      window.addEventListener("resize", this.onWindowResize, {
        passive: false,
      });
      document.addEventListener("mousemove", this.onDocumentMouseMove, {
        passive: false,
      });
      document.addEventListener("touchstart", this.onDocumentTouchStart, {
        passive: false,
      });
      document.addEventListener("touchmove", this.onDocumentTouchMove, {
        passive: false,
      });
    },
    render: function () {
      this.camera.position.x += (this.mouseX - this.camera.position.x) * 0.05;
      this.camera.position.y = 400;
      this.camera.lookAt(this.scene.position);
      const positions = this.particles.geometry.attributes.position.array;
      const scales = this.particles.geometry.attributes.scale.array;
      // 计算粒子位置及大小
      let i = 0;
      let j = 0;
      for (let ix = 0; ix < this.amountX; ix++) {
        for (let iy = 0; iy < this.amountY; iy++) {
          positions[i + 1] =
            Math.sin((ix + this.count) * 0.3) * 100 +
            Math.sin((iy + this.count) * 0.5) * 100;
          scales[j] =
            (Math.sin((ix + this.count) * 0.3) + 1) * 8 +
            (Math.sin((iy + this.count) * 0.5) + 1) * 8;
          i += 3;
          j++;
        }
      }
      // 重新渲染粒子
      this.particles.geometry.attributes.position.needsUpdate = true;
      this.particles.geometry.attributes.scale.needsUpdate = true;
      this.renderer.render(this.scene, this.camera);
      this.count += 0.1;
    },
    animate: function () {
      requestAnimationFrame(this.animate);
      this.render();
    },
    onDocumentMouseMove: function (event) {
      this.mouseX = event.clientX - this.windowHalfX;
    },
    onDocumentTouchStart: function (event) {
      if (event.touches.length === 1) {
        this.mouseX = event.touches[0].pageX - this.windowHalfX;
      }
    },
    onDocumentTouchMove: function (event) {
      if (event.touches.length === 1) {
        event.preventDefault();
        this.mouseX = event.touches[0].pageX - this.windowHalfX;
      }
    },
    onWindowResize: function () {
      this.windowHalfX = window.innerWidth / 2;
      this.camera.aspect = window.innerWidth / window.innerHeight;
      this.camera.updateProjectionMatrix();
      // this.renderer.setSize(window.innerWidth, window.innerHeight); 引起拉伸空白問題
    },

    //////////////////////////////////////////////////粒子

     ////////////MQTT
    // 创建MQTT主題连接
    sysConnection() {
      // 连接字符串, 通过协议指定使用的连接方式

      const options = {
        connectTimeout: 40000,
        clientId: "vuePC-" + this.qrtxt,  //随便 唯一
        username: "admin",
        password: "public",
        clean: true,
      };

      // const connectUrl = `ws://192.169.0.39:8083/mqtt`;
      const connectUrl = `ws://119.23.211.181:8083/mqtt`;
      try {
        this.client = mqtt.connect(connectUrl, options);
      } catch (error) {
        console.log("mqtt.connect error", error);
      }
      // mqtt连接
      this.client.on("connect", () => {
        console.log("Connection succeeded!");

        //消息订阅
         this.client.subscribe(this.qrtxt, { qos: 1 }, (error) => {
        if (!error) {
          console.log("订阅成功");
        } else {
          console.log("订阅失败");
        }
      });


      });
      // 链接异常处理
      this.client.on("error", (error) => {
        console.log("Connection failed", error);
      });
      // 接收消息处理
      this.client.on("message", (topic, message) => {

        // console.log(message);

        let data = JSON.parse(message);
        // console.log(data);
        // console.log(this.navs);
        if(!data.msg || data.msg == "undefined" || data.msg == "null")
         return
       

          if(data.msg.indexOf("登录") >= 0||data.msg.indexOf("登陆") >= 0){
           setToken(data.token);
           this.getList();
           this.$router.push({ name: "Home" });
          } else if(data.msg.indexOf("退出") >= 0||data.msg.indexOf("退出登陆") >= 0){
            // 退出登录
           this.logout();
          }else {
             // 1.筛选出key对应的导航
          let nav_index = this.navs.findIndex((item) => data.msg.indexOf(item.command) >= 0);
          let nav_obj = this.navs[nav_index];

          // console.log(nav_obj);
          if(nav_obj)
          this.$router.push(nav_obj.path);
          else
          // this.$message.error("指令,不存在或错误！");
            this.$notify({
              title: '指令,不存在或错误！',
              message: data.msg,
              position: 'bottom-right',
              type: 'warning'
            });
         }


      });

      
    },
    // 创建主題连接

    //断开连接
    destroyConnection() {
        try {
          this.client.end();
          console.log("Successfully disconnected!");
        } catch (error) {
          console.log("Disconnect failed", error.toString());
        }
    },

    ////////////MQTT
     /** 查询菜单路由列表  扫码登录成功后调用  MQ跳转用*/
    getList() {

      let queryParams = {
        menuType: 'C',
        }

      listMenu(queryParams).then(response => {
        this.navs = response.data.data;
      });
    },
    async logout() {
           //确定
          this.$delet(
            "/auth/logout",
            {},
            (data) => {
              this.$message({ message: "退出成功", type: "success" });
              this.$router.push({ name: "Login" });
              // this.$router.replace("/");
            },
            (error) => {
              this.$message.error(error.msg);
            }
          );

    }

  },
  mounted() {

    removeToken();
    //粒子
    this.init();
    this.animate();
    //粒子

    this.destroyConnection();
  },
};
</script>

<style lang="less" scoped>
.login {
  background: url(~@/assets/login_bgJSPT.jpg) no-repeat fixed center;
  background-size: 100vw 100vh;
  width: 100vw;
  height: 100vh;
  position: relative;
}
.toppng {
  z-index: 1000;
  position: absolute;
  top: 32vh;
  left: 20vw;
  background: url(~@/assets/top.png);
  background-size: 20vw 20vw;
  width: 20vw;
  height: 20vw;
}

.login-title {
  font-weight: 700;
  font-size: 56px;
  color: #ffffff;
  position: absolute;
  top: 3vh;
  left: 12vw;
}
.logo {
  width: 58px;
  height: 58px;
  vertical-align: middle;
}
.login-area {
  z-index: 1000;
  width: 480px;
  height: 440px;
  position: absolute;
  top: 18vh;
  right: 15vw;
  background: #fff;
  border: 1px solid #1a629c;
  background-image: url(~@/assets/code_qr.png);
  background-repeat: no-repeat;
  background-position: 100% 0;
  background-origin: content-box;
  background-size: 53px 53px;
}
.qrimmg-area {
  width: 53px;
  height: 53px;
  position: absolute;
  top: 0;
  right: 0;
}
.login-area-title {
  margin: 30px;
  font-size: 24px;
  color: #1e1e1e;
  text-align: center;
}
.login-from {
  margin: 0 60px;
  position: relative;
}
.login-tab {
  position: relative;
  margin-bottom: 20px;
}
.tab-nav {
  margin: 0 20px;
  overflow: hidden;
}
.tab-nav li {
  float: left;
  width: 50%;
  line-height: 45px;
  text-align: center;
  font-size: 20px;
  color: #1e1e1e;
  cursor: pointer;
}
.tab-border {
  width: 85px;
  height: 5px;
  background: #2062fe;
  position: absolute;
  left: 60px;
  bottom: 0;
  transition: all 1s;
  -o-transition: all 1s;
  -moz-transition: all 1s;
  -webkit-transition: all 1s;
}
.is-tab {
  left: 219px;
}
.verification-img {
  width: 120px;
  height: 38px;
}
.verification-img img {
  width: 100%;
  height: 100%;
}
// .login-from .el-input__inner {
//   border-radius: 0;
//   border-color: #85c8f8;
//   height: 45px;
//   font-size: 18px;

// }
.el-input {
  border-radius: 0;
  border-color: #85c8f8;
  height: 45px;
  font-size: 16px;
}
.login-from .el-input__icon {
  color: #33a7f6;
}
.login-from .el-button {
  letter-spacing: 12px;
  width: 100%;
  background-color: #2062fe;
  border-radius: 0;
  font-weight: 700;
  font-size: 18px;
  color: #ffffff;
}
.login-from .el-button:hover {
  background-color: #3e77fd;
}
.login-link {
  font-size: 12px;
  color: #333333;
}
.login-link span {
  cursor: pointer;
}
.login-link span:hover {
  color: #26a6fe;
}
.forget-pwd {
  float: right;
  line-height: normal;
  margin: 12px 0;
}
.divide-wrap {
  margin: 40px 100px 0 100px;
}
.divide-wrap .el-divider__text {
  color: #999999;
  font-size: 14px;
}
.icon-list {
  margin: 30px 70px 0 70px;
  overflow: hidden;
}
.icon-list li {
  width: 50%;
  float: left;
  text-align: center;
  cursor: pointer;
}
.icon-list img {
  width: 36px;
  height: 36px;
}

/*该样式最终是以弹窗插入*/
// .sliding-pictures {
//   width: 100%;
//   .operation {
//     width: 100%;
//     height: 40px;
//     > span {
//       color: #9fa3ac;
//       display: inline-block;
//       width: 40px;
//       font-size: 25px;
//       line-height: 40px;
//       text-align: center;
//       &:hover {
//         background: #e2e8f5;
//       }
//     }
//   }
// }

.verPopover {
  width: 380px;
  height: 340px;
  position: absolute;
  z-index: 2000;
  top: 26%;
  right: 18.5%;
}

.qrbody {
  width: 370px;
  height: 370px;
  text-align: center;
  position: absolute;
  z-index: 1000;
  top: 26vh;
  right: 18vw;
  background: #fff;
}
.top-text {
  margin-top: 10px;
  font-size: 18px;
  font-weight: 600;
  color: #097bdb;
}
</style>
